<?php
namespace Util;

use Think\Controller;

class AccessController extends Controller {
    private $AccessExpire;
    private $AccessName;
    private $AccessField;
    private $AccessRedir;
    private $AccessMiss;

    public function __construct() {
        parent::__construct();

        $this->setAccess();
        $time = $this->isSession();

        /*
         * 权限拦截
         */
        if ($this->isintercept() && !$this->S('AccessInterceptOK')) {
            redirect(U('User/index'));
            exit();
        }

        /*
         * 拦截跳过
         */
        if ($this->isMiss()) {
            return true;
        }


        if ($time) {
            if ($this->isExpire($time)) {
                /*验证完成后执行,用户自定义行为*/
                $this->Hook();
                return;
            }
        }

        if (isset($_SERVER["HTTP_X_REQUESTED_WITH"])
            && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest"
        ) {
            // ajax 请求的处理方式
            echo 'UNLOGIN';
            exit();
        } else {
            if ($_GET['mao']) {
                redirect(U('Login/user_login'));
            }
            redirect(U($this->AccessRedir) . '?PrevURL=' . $_SERVER['REQUEST_URI']);
        }
    }

    public function S($data, $value) {
        if (isset($value) && !empty($value)) {
            $_SESSION[$this->AccessName]['DATA'][$data] = $value;
        }
        if ($value == '_REMOVE_') {
            unset($_SESSION[$this->AccessName]['DATA'][$data]);
            return;
        }
        if ($data == '_REMOVE_') {
            unset($_SESSION[$this->AccessName]);
            return;
        }
        if (is_string($data)) {
            if (strtoupper($data) == 'REGIST') {
                return $_SESSION[$this->AccessName]['REGIST'];
            }
            return $_SESSION[$this->AccessName]['DATA'][$data];
        } elseif (is_array($data)) {
            if (empty($_SESSION[$this->AccessName]['DATA'])) {
                $data = array(
                    "DATA" => $data,
                    "EXPIRE" => time(),
                    "REGIST" => time()
                );
                $_SESSION[$this->AccessName] = $data;
            } else {
                $res = $_SESSION[$this->AccessName]['DATA'];
                foreach ($res as $key => $value) {
                    $data[$key] = $value;
                }
                $data = array(
                    "DATA" => $data,
                    "EXPIRE" => time(),
                    "REGIST" => time()
                );
                $_SESSION[$this->AccessName] = $data;
            }

            if ($this->AccessField != 'FILE') {
                $PHPSESSID = $_COOKIE['PHPSESSID'];
                /*缓存服务器同步*/
                $data['SYNCH'] = true;
                S($PHPSESSID, $data, $this->AccessExpire);
            }
        } else {
            return $_SESSION[$this->AccessName]['DATA'];
        }
    }

    private function isMiss() {
        $class = get_class($this);

        foreach ($this->AccessMiss as $v) {
            if (strpos($v, '/')) {
                if ($_SERVER['PATH_INFO'] == $v) {
                    return true;
                }
            } elseif (strpos($class, $v . 'Controller'))
                return true;
        }

        return false;
    }

    /*
     * 作者 ：mao
     * 再次拦截的Controller
     * 一般用于权限问题
     */
    private function isintercept() {
        $class = get_class($this);
        foreach (C('AccessIntercept') as $v) {
            if (strpos($v, '/')) {
                if ($_SERVER['PATH_INFO'] == $v) {
                    return true;
                }
            } elseif (strpos($class, $v . 'Controller'))
                return true;
        }
        return false;
    }

    /**
     * [set 初始化配置项属性]
     * @Author   :seven
     * @DateTime :2016-06-11T22:19:13+0800
     * @Detail   :
     */
    private function setAccess($time) {
        $this->AccessExpire = is_null(C('SESSION_EXPIRE'))
            ? 1800
            : C('SESSION_EXPIRE') * 60;

        $this->AccessName = is_null(C('SESSION_NAME'))
            ? strtoupper(C('GROUP_NAME')) . '_SESSION'
            : C('SESSION_NAME');

        $this->AccessField = is_null(C('SESSION_FIELD'))
            ? 'FILE'
            : strtoupper(C('SESSION_FIELD'));

        $this->AccessRedir = is_null(C('SESSION_REDIR'))
            ? '/' . C('GROUP_NAME') . '/Login/index'
            : '/' . C('GROUP_NAME') . '/' . C('SESSION_REDIR');
        $this->AccessMiss = is_null(C('SESSION_MISS'))
            ? array('Login')
            : C('SESSION_MISS');

    }

    /**
     * [isExpire 是否过期]
     * @Author   :seven
     * @DateTime :2016-06-11T22:20:13+0800
     * @Detail   :
     * @return   boolean    [true 过期]
     */
    private function isExpire($expire) {
        $expire = time() - $expire;
        if ($expire > $this->AccessExpire) {
            return false;
        }
        /*续签SESSION*/
        $_SESSION[$this->AccessName]['EXPIRE'] = time();
        return true;
    }

    /**
     * [isSession 查询是否已登录]
     * @Author   :seven
     * @DateTime :2016-06-11T22:27:26+0800
     * @Detail   :
     * @return   boolean    [true 已经登录]
     */
    private function isSession() {
        if ($this->AccessField == 'FILE') {
            return $this->isFSession();
        } else {
            return $this->isRSession();
        }
    }

    /**
     * [isFSession 默认使用$_SESSION]
     * @Author   :seven
     * @DateTime :2016-06-11T23:19:14+0800
     * @Detail   :
     * @return   boolean                   [description]
     */
    private function isFSession() {
        if ($_SESSION[$this->AccessName]) {
            return $_SESSION[$this->AccessName]['EXPIRE'];
        }
        return false;
    }

    /**
     * [isRSession 可选用远程缓存形式]
     * @Author   :seven
     * @DateTime :2016-06-11T23:19:37+0800
     * @Detail   :
     * @return   boolean    [true 已经登录]
     */
    private function isRSession() {
        $PHPSESSID = $_COOKIE['PHPSESSID'];
        if (empty($PHPSESSID)) {
            return;
        }

        $data = S($PHPSESSID);
        if (empty($data)) {
            return;
        }
        /*从缓存服务器同步到本地*/
        if ($data['SYNCH']) {
            $data = array(
                "DATA" => $data['DATA'],
                "EXPIRE" => time(),
                "REGIST" => time()
            );
            $_SESSION[$this->AccessName] = $data;
            $data['SYNCH'] = false;
            /*更新缓存服务器状态*/
            S($PHPSESSID, $data, $this->AccessExpire);
        }

        if (!empty($_SESSION[$this->AccessName])) {
            /*已同步到现在的服务器上*/
            return $_SESSION[$this->AccessName]['EXPIRE'];
        }

    }

    protected function Hook() {

    }
}